
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       storage_manager.h
  * @author     baiyang
  * @date       2021-8-8
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include <stdbool.h>
#include <stdint.h>

#include <rtthread.h>
#include <rtconfig.h>

#if defined(RT_USING_FAL)
#include <fal.h>
#endif
/*-----------------------------------macro------------------------------------*/
#define STORAGE_MISSION_LENGTH 1024*3
#define STORAGE_KEYS_LENGTH 64
/*----------------------------------typedef-----------------------------------*/
typedef enum {
    StorageParam   = 0,
    StorageFence   = 1,
    StorageRally   = 2,
    StorageMission = 3,
    StorageKeys    = 4,
    StorageBindInfo= 5,
    StorageCANDNA  = 6,
    StorageParamBak = 7
} StorageType;

typedef struct StorageAccess* storage_access_t;

struct StorageAccess
{
    StorageType type;
    uint32_t total_size;

#if defined(RT_USING_FAL)
    const struct fal_partition * storage_dev;
#else
    // each bit of the dirty mask covers 1k of data
    uint64_t dirty_mask;
    int fd;
    uint8_t *buff;

    // mutex for access to shared frontend data
    struct rt_mutex _mutex;
#endif
};

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
//
void StorageAccess_init(storage_access_t storage, StorageType type);

// base access via block functions
bool StorageAccess_read_block(const struct StorageAccess* storage, void *data, uint32_t addr, uint32_t n);
bool StorageAccess_write_block(struct StorageAccess* storage, uint32_t addr, const void *data, uint32_t n);

/*
  copy one area to another
 */
bool StorageAccess_copy_area(storage_access_t storage, const struct StorageAccess* source);

#if !defined(RT_USING_FAL)
bool StorageAccess_attach_file(storage_access_t storage, const char *filename);
#endif

// return total size of this accessor
static inline uint32_t StorageAccess_size(const struct StorageAccess* storage) {
    return storage->total_size;
}

/*
  read a byte
 */
static inline uint8_t StorageAccess_read_byte(storage_access_t storage, uint32_t loc) {
    uint8_t v;
    StorageAccess_read_block(storage, &v, loc, sizeof(v));
    return v;
}

/*
  read 8 bit value
 */
static inline uint8_t StorageAccess_read_uint8(storage_access_t storage, uint32_t loc) {
    return StorageAccess_read_byte(storage, loc);
}

/*
  read 16 bit value
 */
static inline uint16_t StorageAccess_read_uint16(storage_access_t storage, uint32_t loc) {
    uint16_t v;
    StorageAccess_read_block(storage, &v, loc, sizeof(v));
    return v;
}

/*
  read 32 bit value
 */
static inline uint32_t StorageAccess_read_uint32(storage_access_t storage, uint32_t loc) {
    uint32_t v;
    StorageAccess_read_block(storage, &v, loc, sizeof(v));
    return v;
}

/*
  read a float
 */
static inline float StorageAccess_read_float(storage_access_t storage, uint32_t loc) {
    float v;
    StorageAccess_read_block(storage, &v, loc, sizeof(v));
    return v;
}

/*
  write a byte
 */
static inline void StorageAccess_write_byte(storage_access_t storage, uint32_t loc, uint8_t value) {
    StorageAccess_write_block(storage, loc, &value, sizeof(value));
}

/*
  write a uint8
 */
static inline void StorageAccess_write_uint8(storage_access_t storage, uint32_t loc, uint8_t value) {
    StorageAccess_write_byte(storage, loc, value);
}

/*
  write a uint16
 */
static inline void StorageAccess_write_uint16(storage_access_t storage, uint32_t loc, uint16_t value) {
    StorageAccess_write_block(storage, loc, &value, sizeof(value));
}

/*
  write a uint32
 */
static inline void StorageAccess_write_uint32(storage_access_t storage, uint32_t loc, uint32_t value) {
    StorageAccess_write_block(storage, loc, &value, sizeof(value));
}

/*
  write a float
 */
static inline void StorageAccess_write_float(storage_access_t storage, uint32_t loc, float value) {
    StorageAccess_write_block(storage, loc, &value, sizeof(value));
}

/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



